<?php
class fpsUser {
	static $USERS = array();
	static $USER = null;

	static function init() {
		fps_define('FPS_USER_SESSION_KEY', 'FPS_USER');
		fps_define('FPS_USER_COOKIE_KEY', 'FPS_USER');
		fps_define('FPS_USER_SERVER_TOKEN', '');
		if (FPS_USER_SERVER_TOKEN == '') {
			echo 'Warning: Miss `FPS_USER_SERVER_TOKEN` setting';
		}
	}

	static function id() {
		$user = self::get();
		return $user['_id'];
	}

	static function get() {
		if (!self::$USER){
			self::$USER = array(
				'_id' => 0,
				'name' => 'Guest',
				'email' => 'guest@fps',
				'pass' => '',
				'auth' => ''
			);

			$uid = isset($_SESSION[FPS_USER_SESSION_KEY]) ?
				$_SESSION[FPS_USER_SESSION_KEY] : 0;

			if ($uid <= 0){
				$uid = self::decode_token();
			}
			if ($uid > 0){
				$user = fpsDB::byId(FPS_USER_TABLE, $uid);
				if ($user){
					self::$USERS[$uid] = $user;
					self::$USER = $user;
					$_SESSION[FPS_USER_SESSION_KEY] = $user['_id'];
				}
				else {
					self::kick();
				}
			}
		}
		return self::$USER;
	}

	static function set($user, $timeout=86400) {
		if ($user && $user['_id'] > 0) {
			self::$USER = $user;
			$_SESSION[FPS_USER_SESSION_KEY] = $user['_id'];
			self::set_token($user['_id'], $timeout);
		}
		else {
			self::kick();
		}
	}

	static function kick() {
		$_SESSION[FPS_USER_SESSION_KEY] = 0;
		self::set_token(0);
	}

	static function decode_token() {
		$token = self::get_token();
		if ($token) {
			// check login token to do auto login
			$tokens = explode('-', $token);
			if (count($tokens) == 4) {
				$uid     = $tokens[0];
				$timeout = intval($tokens[1]);
				$salt    = $tokens[2];
				$stoken  = FPS_USER_SERVER_TOKEN;

				if ($timeout > time() && $uid > 0 && !empty($salt)) {
					$sign = md5("$uid|$timeout|$stoken|$salt");
					if ($sign == $tokens[3]) {
						// pass token check, login user
						return intval($uid);
					}
				}
			}
			// remove token
			self::set_token(0);
		}

		return 0;
	}

	static function by_openid($id) {
	    return fpsDB::findOne(FPS_USER_TABLE, ['openid' => $id]);
    }

	static function by_id($uid) {
		if (isset(self::$USERS[$uid])) {
			return self::$USERS[$uid];
		}
		else {
			$user = fpsDB::byId(FPS_USER_TABLE, $uid);
			self::$USERS[$uid] = $user;
			return $user;
		}
	}

	static function by_email($email) {
	    return fpsDB::findOne(FPS_USER_TABLE, ['email' => $email]);
    }

	static function username($uid) {
		if ($uid <= 0) {
			return '-';
		}
		$user = self::by_id($uid);

		return $user ? htmlspecialchars($user['name']) : '<i>Unknow</i>';
	}

	static function email($uid) {
		if ($uid <= 0) {
			return '-';
		}
		$user = self::by_id($uid);

		return $user ? htmlspecialchars($user['email']) : '<i>Unknow</i>';
	}

	static function get_token() {
		if (isset($_SERVER[FPS_ENV][FPS_USER_COOKIE_KEY])) {
			return $_SERVER[FPS_ENV][FPS_USER_COOKIE_KEY];
		}
		if (isset($_COOKIE[FPS_USER_COOKIE_KEY])) {
			return $_COOKIE[FPS_USER_COOKIE_KEY];
		}
		else {
			return '';
		}
	}

	static function set_token($uid, $timeout=86400){
		$token = '';
		if ($uid > 0 && $timeout > 0) {
			$timeout += time();
			$salt = rand();
			$stoken = FPS_USER_SERVER_TOKEN;
			$sign = md5("$uid|$timeout|$stoken|$salt");
			$token = "$uid-$timeout-$salt-$sign";

			setcookie(
				FPS_USER_COOKIE_KEY, $token,
				$timeout, '/', null, false, true
			);
		}
		else {
			// no timeout, remove token, just session login
			setcookie(FPS_USER_COOKIE_KEY, '', 0, '/');
		}

		$_SERVER[FPS_ENV][FPS_USER_COOKIE_KEY] = $token;
		$_COOKIE[FPS_USER_COOKIE_KEY] = $token;
	}

	static function get_sid() {
		return session_id();
	}
}